﻿namespace ShadowCode.Injection;
internal partial class Error(string message, SyntaxNode? node = null) : Exception(message)
{
    public static DiagnosticDescriptor Create(string id,
     string? description = null,
     string messageFormat = "{0}",
     string title = "ShadowCode.Injection",
     string category = "ShadowCode",
     DiagnosticSeverity severity = DiagnosticSeverity.Error) =>
     new(id, title, messageFormat, category, severity, true, description);

    /// <summary>
    /// 找不到指定名称的函数
    /// </summary>
    internal static DiagnosticDescriptor NotFoundMethodName { get; } = Create("sc01", """
    Factory 设置为字符串时，会查找当前类下的所有静态方法，建议使用 nameof('静态方法名称')。
    签名要求如下：
    标准: Func<IServiceProvider, TService>
    键控: Func<IServiceProvider, object?, TService>
    """);

    /// <summary>
    /// 标准服务签名错误
    /// </summary>
    internal static DiagnosticDescriptor StandardSignatureError { get; } = Create("sc02", """
    签名要求如下：
    标准: Func<IServiceProvider, TService>
    """);

    /// <summary>
    /// 键控服务签名错误
    /// </summary>
    internal static DiagnosticDescriptor KeydSignatureError { get; } = Create("sc03", """
    签名要求如下：
    键控: Func<IServiceProvider, object?>
    """);

    /// <summary>
    /// 要求静态
    /// </summary>
    internal static DiagnosticDescriptor RequiredStatic { get; } = Create("sc04");

    /// <summary>
    /// 不能在构造函数上使用Factory
    /// </summary>
    internal static DiagnosticDescriptor ProhibitFactory { get; } = Create("sc05");

    /// <summary>
    /// 不支持在泛型类的构造函数上使用！
    /// </summary>
    internal static DiagnosticDescriptor NotGeneric { get; } = Create("sc06");

    /// <summary>
    /// 不支持的用法
    /// </summary>
    internal static DiagnosticDescriptor NotSupported { get; } = Create("sc07");

    /// <summary>
    /// 要求泛型实参
    /// </summary>
    internal static DiagnosticDescriptor RequireGenericArguments { get; } = Create("sc08", """
    例如: [AddService<IService<string>>()] 
          class MyClass<T> : IService<T> { }

    或者  [AddService(ServiceType = typeof(IService<>))]   
          class MyClass<T> : IService<T> { }
    """);

    /// <summary>
    /// 非预期表达式
    /// </summary>
    internal static DiagnosticDescriptor Unexpected { get; } = Create("sc00");

    public DiagnosticDescriptor Value { get; set; } = Unexpected;

    public SyntaxNode? Node { get; set; } = node;


    /// <summary>
    /// 非预期表达式
    /// </summary>
    public static Error CreateUnexpected(SyntaxNode? node = null) => new($"非预期表达式:{node}");

    public Diagnostic Diagnostic => Diagnostic.Create(Value, Node?.GetLocation(), Message);

    internal static void CheckInstanceType(INamedTypeSymbol type,
        Compilation compilation, SyntaxNode node)
    {
        if (!type.TypeArguments.Any(x => x.IsTypeParameter())) return;
        var newType = compilation.GetSampleType(type.OriginalDefinition);
        var msg = $"不支持{type}, 需指定类型实参,例如 {newType}";
        throw NotGeneric.CreateError(msg, node);
    }
}


internal static class ErrorExtEnd
{
    public static Error CreateError(this DiagnosticDescriptor dd, string message, SyntaxNode? node = null) =>
        new(message, node) { Value = dd };
}